using System;
using System.Collections.Generic;
using Xunit;
using WenYu.Core.Lexer;
using WenYu.Core.Parser;

namespace WenYu.Tests.DocumentValidation;

/// <summary>
/// 文档02-数据类型与变量.md的示例验证测试
/// </summary>
public class Doc02TypesAndVariablesValidation
{
    private List<Token> Tokenize(string source)
    {
        var lexer = new WenYuLexer(source);
        return lexer.Tokenize();
    }

    private Program Parse(string source)
    {
        var lexer = new WenYuLexer(source);
        var tokens = lexer.Tokenize();
        var parser = new WenYuParser(tokens);
        return parser.Parse();
    }

    #region 基本类型测试

    [Fact]
    public void Example1_IntegerType()
    {
        var source = @"整型 年龄 是 10。
整型 温度 是 -5。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example2_FloatType()
    {
        var source = @"实型 身高 是 1.45。
实型 价格 是 99.99。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example3_StringType()
    {
        var source = @"文字 姓名 是 ""小明""。
文字 问候 是 ""你好世界""。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example4_BoolType()
    {
        var source = @"真假 是学生 是 真真。
真假 下雨了 是 假假。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        
        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }
        
        Assert.Contains("真真", tokenValues);
        Assert.Contains("假假", tokenValues);
        
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 变量声明和赋值测试

    [Fact]
    public void Example5_VarDeclarationOnly()
    {
        var source = @"整型 年龄。
文字 姓名。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example6_VarDeclarationWithAssignment()
    {
        var source = @"整型 年龄 是 10。
实型 身高 是 1.45。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example7_ReAssignment()
    {
        var source = @"整型 分数 是 85。
分数 是 90。
分数 是 分数 + 5。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 新关键字测试

    [Fact]
    public void Example8_AutoTypeInference_设()
    {
        var source = @"设 甲 是 100。
设 乙 是 3.14。
设 丙 是 ""你好""。
设 丁 是 真真。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Check if "设" keyword is recognized
        Assert.Contains("设", tokenValues);

        try
        {
            var ast = Parse(source);
            Assert.NotNull(ast);
        }
        catch (Exception ex)
        {
            Assert.Fail($"设 keyword parsing failed: {ex.Message}");
        }
    }

    #endregion

    #region 类型转换测试

    [Fact]
    public void Example9_TypeConversion_的文字()
    {
        var source = @"整型 年龄 是 10。
文字 年龄文字 是 年龄的文字。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        try
        {
            var ast = Parse(source);
            Assert.NotNull(ast);
        }
        catch (Exception ex)
        {
            Assert.Fail($"的文字 property parsing failed: {ex.Message}");
        }
    }

    [Fact]
    public void Example10_StringConcatenation()
    {
        var source = @"整型 年龄 是 10。
输出（""年龄是："" + 年龄的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        try
        {
            var ast = Parse(source);
            Assert.NotNull(ast);
        }
        catch (Exception ex)
        {
            Assert.Fail($"String concatenation parsing failed: {ex.Message}");
        }
    }

    #endregion

    #region 比较和条件测试

    [Fact]
    public void Example11_ComparisonOperator_同()
    {
        var source = @"真假 是学生 是 真真。
若 是学生 同 真真 则{
    输出（""是学生""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Check if "同" keyword is recognized
        Assert.Contains("同", tokenValues);

        try
        {
            var ast = Parse(source);
            Assert.NotNull(ast);
        }
        catch (Exception ex)
        {
            Assert.Fail($"同 keyword parsing failed: {ex.Message}");
        }
    }

    [Fact]
    public void Example12_ElseKeyword_余()
    {
        var source = @"若 真真 则{
    输出（""真""）。
}余{
    输出（""假""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Check if "余" keyword is recognized
        Assert.Contains("余", tokenValues);

        try
        {
            var ast = Parse(source);
            Assert.NotNull(ast);
        }
        catch (Exception ex)
        {
            Assert.Fail($"余 keyword parsing failed: {ex.Message}");
        }
    }

    #endregion
}
